#include "GUIPartRobot.h"
#include <qdebug.h>

/**
 * @fn	GUIPartRobot::GUIPartRobot(const QList<QPixmap> &animation, QGraphicsScene *scene)
 *
 * @brief	Constructor.
 *
 * @author	Sean Saleh
 *
 * @param	animation	 	The animation.
 * @param [in,out]	scene	If non-null, the scene.
 * 					
 * TODO:
 * set Parts that I hold to be in a specific location
 * Verify data in non-normative
 */

GUIPartRobot::GUIPartRobot(int startX, int startY)
	: GUIBase()
{
	loadImage("Resources/Sprites/Part Robot/PartRobot.png");
	loadImage("Resources/Sprites/Part Robot/PartRobotBroken.png");

	this->setOriginCenter();

	this->setX(startX);
	this->setY(startY);
	this->setZValue(ZVALUE_PARTROBOT);
	this->startX = startX;
	this->startY = startY;

	state = Idle;
	broken = false;

	for (int x = 0; x < 4; x++)				//initialize vector of hands
		heldParts.push_back(NULL);

	this->host=NULL;
	this->setMovementSpeed(5);
	this->setRotationSpeed(20);
}

/**
 * @fn	void GUIPartRobot::doPickup(GUINest* targetNestIn, int handNum)
 *
 * @brief	Executes the pickup operation.
 *
 * @author	Sean Saleh
 *
 * @param [in,out]	targetNestIn	If non-null, target nest in.
 * @param	handNum					The hand number.
 */

void GUIPartRobot::doPickup(GUINest* targetNestIn, int handNum)
{													//go to targetNest.x,.y
	currentHand = handNum;							//set internal state for which hand is being used
	this->targetNest=targetNestIn;					//store pointer to target nest
	this->moveTo(targetNest->x(), targetNest->y());	//start moving to target mest
	this->state = GoingToPickup;					//sets the state as on the way to pickup
}

/**
 * @fn	void GUIPartRobot::doDumpLoad(Kit* kitDestIn)
 *
 * @brief	Executes the dump load operation.
 *
 * @author	Sean Saleh
 *
 * @param [in,out]	kitDestIn	If non-null, the kit destination in.
 */

void GUIPartRobot::doDumpLoad(Kit* kitDestIn)
{
	this->kitDest=kitDestIn;					//Store point to destination kit
	this->moveTo(kitDest->x(), kitDest->y());	//Set movement to destination kit's x,y
	this-> state = GoingToDump;					//Sets the state as on the way to dump the load
}

/**
 * @fn	void GUIPartRobot::advance(int phase)
 *
 * @brief	Advances the robot to its destination, also calls update loop
 *
 * @author	Sean Saleh
 *
 * @param	phase	The phase.
 */

void GUIPartRobot::DoBreak()
{
	GUIBase::DoBreak();
	blackAndWhite = false;
	currentAnim = 1;
	this->dropPart();
}

void GUIPartRobot::DoFix()
{
	GUIBase::DoFix();
	currentAnim = 0;
}

void GUIPartRobot::dropPart()
{
	for (int x = 0; x < 4; x++)
		{
			if (heldParts[x] != 0)						//if the hand has a part
			{
				heldParts[x]->setParentItem(NULL);		//stop parenting to me
				//This is complicated to maek it appear randomly nearby
				heldParts[x]->setPos(this->pos().x()+(rand()%((int)this->boundingRect().width())),this->pos().y()+(rand()%((int)this->boundingRect().height())));
				heldParts[x]->rotate(rand()%359);
				heldParts[x]->PartFellOnFloor();
				heldParts[x] = 0;						//NULLify pointer, b/c I no longer have it
				break;
			}
		}
}

void GUIPartRobot::advance(int phase)
{ //this is code from GUIBase
	if(phase==1)
	{
		//Code for when broken
		if(broken&&moving)
			if ((rand() % 40) == 1) //1 in 100 chance of running this update loop
				dropPart();
		//Note: my states are only triggered then the PartRobot is no longer moving
		if(moving)
			move();
		else if (this->state == GoingToPickup)
		{
			this->state = DoingPickup;
			pickUp();
		}
		else if (this->state == GoingToDump)
		{
			this->state = DoingDumping;
			dumpLoad();
		}
		else if (this->state == DoingDumping || this->state == DoingPickup)
			;	//don't change the state to idle if race conditions occur
		else
			this->state = Idle;

		//This code is from GUIBase
		rotateStep();
		scaleStep();
		this->setTransform(transTransform);
		this->setTransform(rotTransform);
		if(movingInstantly)
			this->setPos(destination);
		if(rotatingInstantly){
			this->setRotation(targetRotation);
		}
		movingInstantly=false;
		rotatingInstantly=false;
	}
}

/**
 * @fn	void GUIPartRobot::dumpLoad()
 *
 * @brief	Dumps the load.
 *
 * @author	Sean Saleh
 */

void GUIPartRobot::dumpLoad()
{
	if (kitDest == NULL)									//if there is no kit at destination
	{
		std::cerr << "GUIPartRobot has no pointer to a kit to drop things off at" << std::endl;
		qDebug() << "GUIPartRobot has no pointer to a kit to drop things off at";
	}
	else
	{
														//now loop through all hands
		for (int x = 0; x < 4; x++)
		{
			if (heldParts[x] != 0)						//if the hand has a part
			{
				heldParts[x]->setParentItem(NULL);		//stop parenting to me
				kitDest->addPart(heldParts[x]);			//give the kit that part
				heldParts[x] = 0;						//NULLify pointer, b/c I no longer have it
			}
		}
		if (host!=NULL)
			host->msgPartsDumped();							//tell agent I'm done
	}
	/*
	doneMoving = false;									//no longer going to run this code, am done with all actions at destination
	*/
	this->state = Idle;
	this->moveTo(startX,startY);					//start to reset position to starting location
}

/**
 * @fn	void GUIPartRobot::pickUp()
 *
 * @brief	Pick up.
 *
 * @author	Sean Saleh
 */

void GUIPartRobot::pickUp()
{
	if (targetNest==NULL)								//if there is no target nest to talk to
	{
		std::cerr<<"GUIPartRobot has no pointer to a nest to pick things up at";
		qDebug() <<"GUIPartRobot has no pointer to a nest to pick things up at";
	}
	else
	{	
		heldParts[currentHand]=targetNest->getPart();	//ask targetNest for part

		if (heldParts[currentHand]!=NULL)
		{
			heldParts[currentHand]->setFlag(QGraphicsItem::ItemStacksBehindParent);
			heldParts[currentHand]->setParentItem(this);	//put part parented in hand
				
			if (currentHand == 0)
			{
				heldParts[currentHand]->setPos(this->boundingRect().width()/2 - HOLD_LOC_DIST_FROM_EDGE, 0);
				this->rotateOverTime(90, true);
			}
			else if (currentHand == 1)
			{
				heldParts[currentHand]->setPos(0, -this->boundingRect().height()/2 + HOLD_LOC_DIST_FROM_EDGE);
				this->rotateOverTime(180, true);
			}
			else if (currentHand == 2)	
			{
				heldParts[currentHand]->setPos(-this->boundingRect().width()/2 + HOLD_LOC_DIST_FROM_EDGE, 0);
				this->rotateOverTime(270, true);
			}
			else if (currentHand == 3)
			{
				heldParts[currentHand]->setPos(0, this->boundingRect().height()/2 - HOLD_LOC_DIST_FROM_EDGE);
				this->rotateOverTime(0, true);
			}
		}

		
			if (host!=NULL)
				host->msgPartRetrieved(currentHand, heldParts[currentHand]->partType);//call back to agent
	}
	this->state = Idle;								//Now has nothing to do
	this->moveTo(startX,startY);					//start to reset position to starting location
}

/**
 * @fn	void GUIPartRobot::setHost(PartRobot* Host)
 *
 * @brief	Sets a host.
 *
 * @author	Sean Saleh
 *
 * @param [in,out]	Host	If non-null, the host.
 */

void GUIPartRobot::setHost(PartRobot* agent)
{
	this->host = (PartRobotAgent*)agent;
	this->setGUIBaseAgent((PartRobotAgent*)agent);
}
